#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>

//!!!!!!!!!!!!设备数节点中 一定要添加上 status = "okay";

//在dts文件中，添加新的pinctrl 和节点，在节点中使用GPIO系统
/*		xyt_led_wori{
		#address-cells = <1>;
		#size-cells = <1>;
		compatible = "xyt_led_red";
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_xyt_led>;
		red-led = <&gpio1 19 0>;
		cd-gpios = <&gpio1 19 GPIO_ACTIVE_LOW>;
		status = "okay";
	};
    pinctrl_XYT_GPIO_LED: XYT_LED_RED{
    fsl,pins = <
    MX6UL_PAD_GPIO1_IO04__GPIO1_IO04 0x000010B1
    >;
};
*/
#define GPIOCNT  1
#define GPIONAME "XYT"

typedef struct 
{
    dev_t devid;
    int major;
    int minor;
    int LedBian;
    struct cdev cdev;  
    struct class *class; //自dong创建设备节点
    struct device *device;//设备
    struct device_node *nd; //设备节点
}XGpioLed_Dev;
XGpioLed_Dev GpioLed_Dev;
XGpioLed_Dev *Xdev;

static void LED_Staus(int staus)
{

    if (staus == 0)
    {

    }
    else
    {

    }
}

static int LED_open(struct inode *inode, struct file *fs)
{
    fs->private_data = &GpioLed_Dev;
    return 0;
}

static int LED_release(struct inode *inode, struct file *fs)
{

    return 0;
}
static ssize_t LED_read(struct file *fs, char __user *buff, size_t count, loff_t *loff)
{

    return count;
}
static char Tbuff[2];
static ssize_t LED_write(struct file *fs, const char __user *buff, size_t count, loff_t *opps)
{
 
     XGpioLed_Dev *temp = fs->private_data;
     copy_from_user(Tbuff,buff,1);
     printk("Tbuff = %s\n",Tbuff);
     if(Tbuff[0] == '1')
     {
         gpio_set_value(temp->LedBian, 0);
         printk(" close LED \n");
     }
     else if (Tbuff[0] == '0')
     {
         printk(" open LED \n");
         gpio_set_value(temp->LedBian, 1);
     }
     else 
     {
        printk(" else  LED \n");
     }
    return count;
}
//字符设备操作集合
static struct file_operations LedF = {
    .owner	= THIS_MODULE,
    .open = LED_open,
    .read = LED_read,
    .write = LED_write,
    .release = LED_release,
};


static int __init GPIO_Init(void)
{
    int ret= 0;

    //找设备节点
    GpioLed_Dev.nd = of_find_node_by_path("/xyt_led_wori");
	if(GpioLed_Dev.nd == NULL) {
		printk("gpioled node not find!\r\n");
		return -EINVAL;
	} else {
		printk("gpioled node find!\r\n");
	}
    //寻找GPIO编号
    GpioLed_Dev.LedBian = of_get_named_gpio(GpioLed_Dev.nd,"red-led",0);
    if(GpioLed_Dev.LedBian<0)
    {
        printk("NO GPIO NUM \n"); 
    }
    else
    {
        printk("GPIO NUM = %d\n",GpioLed_Dev.LedBian);
    }
    ret = gpio_direction_output(GpioLed_Dev.LedBian, 1); //输出电平为1  灭
    if(ret < 0)
    {
        printk("can set gpio \n");
    }

    //注册设备号
    GpioLed_Dev.major = 0;
    if(GpioLed_Dev.major == 0)
    {
        alloc_chrdev_region(&GpioLed_Dev.devid,0,GPIOCNT,GPIONAME);
        GpioLed_Dev.major = MAJOR(GpioLed_Dev.devid);
        GpioLed_Dev.minor = MINOR(GpioLed_Dev.devid);
    }
    printk("DEVid = %d \n",GpioLed_Dev.major);
    //初始化cdev
    GpioLed_Dev.cdev.owner = THIS_MODULE;
    cdev_init(&GpioLed_Dev.cdev,&LedF);
    //添加Cdev 和设备号关联
    cdev_add(&GpioLed_Dev.cdev,GpioLed_Dev.devid,GPIOCNT);

    //自动创建设备节点 
    GpioLed_Dev.class = class_create(THIS_MODULE,GPIONAME);
    GpioLed_Dev.device = device_create(GpioLed_Dev.class, NULL, GpioLed_Dev.devid,NULL,GPIONAME);    


    return 0;
}

static void __exit GPIO_Exit(void)
{

    cdev_del(&GpioLed_Dev.cdev);
    unregister_chrdev_region(GpioLed_Dev.devid,GPIOCNT);   
    device_destroy(GpioLed_Dev.class,GpioLed_Dev.devid);
    class_destroy(GpioLed_Dev.class);
}
module_init(GPIO_Init);
module_exit(GPIO_Exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("xyt");




